package org.osami.gateway.watteco;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.logging.Logger;

import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.ServiceProperty;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.device.Constants;
import org.osgi.service.device.Device;
import org.osgi.service.device.Driver;

@Component
@Provides
@Instantiate
public class WattecoSmartplugDriverIPv4 implements Driver {
    private static final Logger logger = Logger.getLogger(WattecoSmartplugDriverIPv4.class.getName());

    @ServiceProperty(name = Constants.DRIVER_ID,
                     value = "org.osami.driver.wattecospipv4-1.0")
    private String driverId;

    @Requires(filter = "(factory.name=org.osami.gateway.watteco.PowerSense)")
    private Factory powerSenseFactory;

    private List<String> attachedSerials;
    private BundleContext bundleContext;

    public WattecoSmartplugDriverIPv4(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
        this.attachedSerials = new ArrayList<String>();
    }

    public int match(ServiceReference reference) throws Exception {
        logger.info("WattecoSmartplugDriverIPv4.match(" + reference + ")");
        String[] categories = (String[]) reference.getProperty(Constants.DEVICE_CATEGORY);
        if (categories != null) {
            if (Arrays.asList(categories).contains("Watteco")) {

                // This device belongs to us :)

                // First try an exact match with serial ...
                String serial = (String) reference.getProperty(Constants.DEVICE_SERIAL);
                if (serial != null) {
                    if (attachedSerials.contains(serial)) {
                        return WattecoSmartplugIPv4.MATCH_SERIAL;
                    }
                }

                // Then try the "device.type" property.
                String type = (String) reference.getProperty("device.type");
                if (type != null) {
                    if ("wattecospipv4".equals(type)) {
                        return WattecoSmartplugIPv4.MATCH_TYPE;
                    }
                }
            }
        }
        return Device.MATCH_NONE;
    }

    public String attach(final ServiceReference reference) throws Exception {

        logger.info("WattecoSmartplugDriverIPv4.attach(" + reference + ")");
        String[] categories = (String[]) reference.getProperty(Constants.DEVICE_CATEGORY);
        if (categories != null) {
            if (Arrays.asList(categories).contains("Watteco")) {

                String type = (String) reference.getProperty("device.type");
                if (type != null && type.equals("wattecospipv4")) {

                    // This device is a Watteco IPv4 smartplug, attach it.
                    String serial = (String) reference.getProperty(Constants.DEVICE_SERIAL);
                    String topic = (String) reference.getProperty("topic");

                    if (!attachedSerials.contains(serial)) {
                        attachedSerials.add(serial);

                        // Create the WattecoSensors ...
                        Dictionary<String, Object> deviceIdFilter = new Hashtable<String, Object>();
                        deviceIdFilter.put("device", "(" + Constants.DEVICE_SERIAL + "=" + serial + ")");

                        System.out.println("Creating PowerSense");
                        Dictionary<String, Object> powerConfiguration = new Hashtable<String, Object>();
                        powerConfiguration.put("device.id", serial);
                        powerConfiguration.put("topic", topic + "/power");
                        powerConfiguration.put("sensor.type", "power");
                        powerConfiguration.put("sensor.model", "unknown");
                        powerConfiguration.put("sense.id", "power");
                        powerConfiguration.put("requires.filters", deviceIdFilter);
                        powerSenseFactory.createComponentInstance(powerConfiguration);
                    }

                    // It is expected to return null if we have directly attached the device to our driver.
                    return null;
                }
            }
        }
        throw new Exception("WattecoSmartplugDriverIPv4 does not know how to handle this device !");
    }
}
